// 现代 JavaScript 事件循环
// 作者：AI助手
// 最后更新：2024年

/**
 * JavaScript 事件循环是实现异步编程的核心机制
 * 组成部分：
 * 1. 调用栈（Call Stack）
 * 2. 任务队列（Task Queue/Macrotask Queue）
 * 3. 微任务队列（Microtask Queue）
 * 4. Web APIs（在浏览器环境中）
 */

// 1. 同步代码和异步代码执行顺序
console.log('1. 开始');

setTimeout(() => {
    console.log('2. 定时器回调');
}, 0);

Promise.resolve()
    .then(() => console.log('3. Promise 回调'));

console.log('4. 结束');

// 输出顺序：
// 1. 开始
// 4. 结束
// 3. Promise 回调
// 2. 定时器回调

// 2. 微任务和宏任务
setTimeout(() => console.log('1. 定时器1'), 0);
setTimeout(() => console.log('2. 定时器2'), 0);

Promise.resolve()
    .then(() => console.log('3. Promise1'))
    .then(() => console.log('4. Promise2'));

Promise.resolve()
    .then(() => console.log('5. Promise3'));

// 3. 复杂示例：任务队列和微任务队列的交互
console.log('开始执行');

// 宏任务1
setTimeout(() => {
    console.log('定时器1');
    // 微任务2
    Promise.resolve().then(() => {
        console.log('Promise2');
    });
}, 0);

// 宏任务2
setTimeout(() => {
    console.log('定时器2');
}, 0);

// 微任务1
Promise.resolve().then(() => {
    console.log('Promise1');
    // 宏任务3
    setTimeout(() => {
        console.log('定时器3');
    }, 0);
});

console.log('同步代码结束');

// 4. 实际应用示例
class AsyncQueue {
    constructor() {
        this.queue = [];
        this.running = false;
    }

    enqueue(task) {
        return new Promise((resolve, reject) => {
            this.queue.push({
                task,
                resolve,
                reject
            });

            if (!this.running) {
                this.processQueue();
            }
        });
    }

    async processQueue() {
        if (this.running) return;
        this.running = true;

        while (this.queue.length > 0) {
            const { task, resolve, reject } = this.queue.shift();
            try {
                // 在下一个微任务中执行
                const result = await Promise.resolve().then(() => task());
                resolve(result);
            } catch (error) {
                reject(error);
            }
        }

        this.running = false;
    }
}

// 5. 示例：不同类型任务的执行顺序
async function demonstrateEventLoop() {
    console.log('1. 同步代码开始');

    // 注册一个宏任务
    setTimeout(() => {
        console.log('2. 第一个宏任务');
        // 在宏任务中注册微任务
        Promise.resolve().then(() => {
            console.log('3. 宏任务中的微任务');
        });
    }, 0);

    // 注册一个微任务
    await Promise.resolve();
    console.log('4. 第一个微任务');

    // 再次注册宏任务
    setTimeout(() => {
        console.log('5. 第二个宏任务');
    }, 0);

    // 同步注册多个微任务
    queueMicrotask(() => {
        console.log('6. 使用 queueMicrotask 注册的微任务');
    });

    Promise.resolve().then(() => {
        console.log('7. Promise 微任务');
    });

    console.log('8. 同步代码结束');
}

// 6. 使用 AsyncQueue 的示例
async function demonstrateAsyncQueue() {
    const queue = new AsyncQueue();

    // 添加多个任务
    queue.enqueue(() => {
        console.log('任务1开始');
        return new Promise(resolve => setTimeout(() => {
            console.log('任务1完成');
            resolve('结果1');
        }, 1000));
    });

    queue.enqueue(() => {
        console.log('任务2开始');
        return new Promise(resolve => setTimeout(() => {
            console.log('任务2完成');
            resolve('结果2');
        }, 500));
    });

    queue.enqueue(() => {
        console.log('任务3开始');
        return Promise.resolve('结果3');
    });
}

// 7. 运行示例
console.log('=== 开始事件循环示例 ===');
demonstrateEventLoop().then(() => {
    console.log('=== 事件循环示例结束 ===');
    console.log('=== 开始异步队列示例 ===');
    return demonstrateAsyncQueue();
}).then(() => {
    console.log('=== 异步队列示例结束 ===');
});

// 8. 最佳实践
// ✅ 使用微任务进行状态更新
function updateState(state) {
    queueMicrotask(() => {
        // 在微任务中更新状态
        console.log('状态已更新:', state);
    });
}

// ✅ 使用宏任务进行计时器和IO操作
function scheduleTask(task) {
    setTimeout(task, 0);
}

// ❌ 避免在循环中创建大量微任务
// for (let i = 0; i < 1000; i++) {
//     Promise.resolve().then(() => console.log(i));
// }

// ❌ 避免在微任务中执行耗时操作
// Promise.resolve().then(() => {
//     // 避免在这里进行大量计算
//     for (let i = 0; i < 1000000000; i++) {}
// }); 